package com.fxu.framework.biz.aop;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fxu.framework.biz.ano.PermAuth;
import com.fxu.framework.biz.util.LoginUtil;
import com.fxu.framework.biz.util.TokenUtil;
import com.fxu.framework.core.enums.BaseEnum;
import com.fxu.framework.core.exception.MsgException;
import com.fxu.framework.core.holder.RequestHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * 权限控制
 * @author fangxu
 * @version 1.0.0
 */
@Slf4j
@Aspect
@Component
public class PermAuthAspect {
    @Pointcut("@annotation(com.fxu.framework.biz.ano.PermAuth)")
    public void pointcut() {
    }

    /**
     * 根据切入点执行
     * PermAuth("/test/index:*") : 所有权限
     * PermAuth("/test/index:list") : 读取列表权限
     * PermAuth("/test/index:list,save") : 读取列表、保存(添加、修改、删除)权限
     * @param joinPoint 切入点
     * @return 返回执行返回
     * @throws Throwable 执行异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //TODO 获取用户token
        //TODO menu 增加一个字段perms[1,2,3]
        //TODO role_menu 增加一个字段perms[1,2,3]
        //TODO 登录权限列表[菜单路由:权限], 目前是[菜单名:权限]
        String token = TokenUtil.getToken(RequestHolder.getRequestMayNull());
        Set<String> permsList = LoginUtil.getPerms(token);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method signatureMethod = signature.getMethod();
        PermAuth permAuth = signatureMethod.getAnnotation(PermAuth.class);
        log.info("permAuth.value={},permsList={}", permAuth.value(), permsList);
        if (hasPerm(permsList, permAuth.value())) {
            return joinPoint.proceed();
        }
        log.error("permAuth.value={},permsList={}", permAuth.value(), permsList);
        throw new MsgException("权限受限制");
    }

    // 判断是否有权限
    private static boolean hasPerm(Set<String> permList, String auth) {
        if (CollUtil.isEmpty(permList) || StrUtil.isEmpty(auth)) {
            return false;
        }
        for (String perm : permList) {
            int permIndex = perm.indexOf(":");
            int authIndex = auth.indexOf(":");
            if (permIndex > 1 && authIndex > 1 && perm.substring(0, permIndex).equals(auth.substring(0, authIndex))) {
                String permTemp = perm.substring(permIndex + 1);
                // * 表示所有权限都有
                if (permTemp.equals("*")) {
                    return true;
                }
                String authTemp = auth.substring(authIndex + 1);
                if (BaseEnum.findOne(StrUtil.splitToArray(permTemp, ","), v -> v.equals(authTemp)) != null) {
                    return true;
                }
            }
        }
        return false;
    }
}


